home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
GL
/
closeup
/
closeup.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
16KB
|
721 lines
/*
* Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/***
closeup.c - image "magnifier" program
Runs under the window manager.
Closeup takes an rgb format image on the command line.
Define XYZOOM as a simple way to demo independent x and y zoom.
(Use 'make "VCDEFS=-DXYZOOM" closeup')
-Rolf
***/
#include <stdio.h>
#include <math.h>
#include <gl.h>
#include <device.h>
#include <image.h>
#include "clang.h"
void Setup();
void HandleEvents();
void SwapImage();
void ReadImage();
void WriteImage();
void DrawIt();
extern char *malloc();
void ShrinkRow();
#define PACK_RGB(rgb,r,g,b) { rgb = \
(((u_char)b) << 16) | (((u_char)g) << 8) | ((u_char)r); }
#define UNPACK_RGB(rgb,r,g,b) { \
r = (rgb) & 0xff; \
g = ((rgb) >> 8) & 0xff; \
b = ((rgb) >> 16) & 0xff; }
long shademode = FLAT ;
char CmdName[] = "closeup";
char UsageStr[] = "usage: closeup image-file";
u_short ir[1280], ig[1280], ib[1280]; /* temps for reading the image file */
typedef struct {
int mousex, mousey; /* source location for magnify */
int width, height; /* size in pixels of the image */
long xorigin, yorigin; /* origin of the window */
int boxwidth, boxheight; /* size of the zooming rectangle */
float xzoom, yzoom; /* x and y zoom factors */
Bool zoommode; /* set when zooming mode is enabled */
RGBvalue *r, *g, *b; /* ptrs to the image */
} StateInfo;
StateInfo StateBlock;
StateInfo *StatePtr = &StateBlock;
void
usage()
{
fprintf(stderr, "%s", UsageStr);
exit(1);
}
/***
Note: getopt code not used yet.
***/
int
main(argc, argv)
char *argv[];
int argc;
{
int c;
extern int getopt(), optind;
extern char * optarg;
#ifdef NOTDEF
while ((c = getopt(argc, argv, "u:")) != EOF) {
switch (c) {
default:
usage();
}
}
#endif
if (argc != 2) {
fprintf(stderr, "%s\n", UsageStr);
exit(1);
}
figure_machine();
{
char *t, *strrchr();
fprintf(stderr, "\n%s: Loading image. Please wait...",
(t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
}
Setup(argv[1], argv[0]);
fprintf(stderr, " Done!\n");
HandleEvents();
/***
clear the overlay planes before exiting
***/
overlay(2);
gconfig();
drawmode(OVERDRAW);
mapcolor(0, 0,0,0);
mapcolor(1, 0,255,255);
color(0);
clear();
drawmode(NORMALDRAW);
return 0;
}
void
Setup(imageName, progname)
char *imageName;
char *progname;
{
char line[100];
int ixzoom, iyzoom;
ReadImage(imageName);
prefsize((long)StatePtr->width,(long)StatePtr->height);
{
char *t, *strrchr();
winopen((t=strrchr(progname, '/')) != NULL ? t+1 : progname);
}
getorigin(&StatePtr->xorigin, &StatePtr->yorigin);
RGBmode();
doublebuffer();
gconfig();
RGBcolor(0, 0, 0);
clear();
swapbuffers();
clear();
zclear();
overlay(2);
gconfig();
drawmode(OVERDRAW);
mapcolor(0, 0,0,0);
mapcolor(1, 0,255,255);
color(0);
clear();
drawmode(NORMALDRAW);
qdevice(LEFTMOUSE);
qdevice(MIDDLEMOUSE);
qdevice(RIGHTMOUSE);
qdevice(INPUTCHANGE);
qdevice(ESCKEY);
qdevice(GKEY);
qdevice(FKEY);
qdevice(WINQUIT);
qdevice(WINSHUT);
StatePtr->xzoom = 5.0;
StatePtr->yzoom = 5.0;
StatePtr->zoommode = FALSE;
ixzoom = (int) (StatePtr->xzoom + .5);
iyzoom = (int) (StatePtr->yzoom + .5);
StatePtr->boxwidth = StatePtr->width / ixzoom;
StatePtr->boxheight = StatePtr->height / iyzoom;
StatePtr->mousex = 0; /* doesn't really matter */
StatePtr->mousey = 0;
WriteImage();
qdevice(TIMER1);
noise(TIMER1, 1);
}
/***
contains the main event loop.
a interval timer is enabled while the window is attached.
the timer is "paused" during time-consuming sequences
to avoid timer events flooding the queue.
***/
void
HandleEvents()
{
short dev, val;
int x, y;
Bool attached = TRUE;
Bool done = FALSE;
#ifdef XYZOOM
Bool xMode = TRUE;
#endif
/* check buttons for mode changes */
while (dev = qread(&val)) {
/* printf("closeup: event: dev=%d,val=%d\n", dev, val); */
unqdevice(TIMER1);
switch (dev) {
case REDRAW:
pushmatrix();
drawmode(OVERDRAW);
fullscrn();
color(0);
clear();
endfullscrn();
popmatrix();
drawmode(NORMALDRAW);
reshapeviewport();
getorigin(&StatePtr->xorigin, &StatePtr->yorigin);
WriteImage();
break;
case LEFTMOUSE:
if (val) {
#ifdef XYZOOM
if (xMode) {
if (StatePtr->xzoom < 31.5) StatePtr->xzoom += 1.0;
}
else {
if (StatePtr->yzoom < 31.5) StatePtr->yzoom += 1.0;
}
#else
if (StatePtr->xzoom < 31.5) StatePtr->xzoom += 1.0;
if (StatePtr->yzoom < 31.5) StatePtr->yzoom += 1.0;
#endif
}
break;
case RIGHTMOUSE:
if (val) {
#ifdef XYZOOM
if (xMode) {
if (StatePtr->xzoom > 2.5) StatePtr->xzoom -= 1.0;
}
else {
if (StatePtr->yzoom > 2.5) StatePtr->yzoom -= 1.0;
}
#else
if (StatePtr->xzoom > 2.5) StatePtr->xzoom -= 1.0;
if (StatePtr->yzoom > 2.5) StatePtr->yzoom -= 1.0;
#endif
}
break;
case INPUTCHANGE:
/***
Note: during development (GL & NeWS) there was trouble
with this mechanism for attaching focus.
just comment out this 'case' if the trouble recurs.
***/
if (val) { /* mouse entered window */
attached = TRUE;
#ifdef XYZOOM
xMode = (xMode) ? FALSE : TRUE;
printf("closeup: updating %s axis\n", (xMode) ? "x":"y");
#endif
}
else {
attached = FALSE;
}
break;
case GKEY:
shademode = GOURAUD ;
break ;
case FKEY:
shademode = FLAT ;
break ;
case ESCKEY:
if (val) break;
case WINQUIT:
done = TRUE;
break;
default:
break;
}
/***
Compute size of zooming rectangle based on zoom factor.
***/
{
int ixzoom = (int) (StatePtr->xzoom + .5);
int iyzoom = (int) (StatePtr->yzoom + .5);
int boxwidth = StatePtr->width / ixzoom;
int boxheight = StatePtr->height / iyzoom;
StatePtr->boxwidth = boxwidth;
StatePtr->boxheight = boxheight;
}
/***
Mouse coords are mapped to the window and clamped
to make the zooming rectangle stay inside the window.
Note: the "+1" below avoids a visible glitch with rectcopy.
***/
StatePtr->mousex = getvaluator(MOUSEX) - StatePtr->xorigin;
StatePtr->mousey = getvaluator(MOUSEY) - StatePtr->yorigin;
if (StatePtr->mousex < 0) {
StatePtr->mousex = 0;
}
if (StatePtr->mousey <= 0) {
StatePtr->mousey = 0 + 1;
}
if (StatePtr->mousex > StatePtr->width - StatePtr->boxwidth - 1) {
StatePtr->mousex = StatePtr->width - StatePtr->boxwidth - 1;
}
if (StatePtr->mousey > StatePtr->height - StatePtr->boxheight - 1) {
StatePtr->mousey = StatePtr->height - StatePtr->boxheight - 1;
}
/***
switch the displayed buffer when mouse is down
***/
if (getbutton(MIDDLEMOUSE)) {
if (StatePtr->zoommode != TRUE) {
StatePtr->zoommode = TRUE;
}
}
else {
if (StatePtr->zoommode != FALSE) {
SwapImage(TRUE); /* copy image from z buffer to back buffer */
swapbuffers();
StatePtr->zoommode = FALSE;
}
}
DrawIt(); /* this may do a swapbuffers() */
if (attached) {
qdevice(TIMER1);
noise(TIMER1, 1);
}
if (done) break;
} /* while... */
}
/***
perform a rectcopy from the z buffer to the back buffer.
adjust the destination size to fit the entire window.
the zooming rectangle is bloated by one pixel (in x and in y)
to ensure that the destination rectangle fills the window.
(different zoom factors affect how well the dest rect fits)
***/
void
DrawIt()
{
int boxwidth = StatePtr->boxwidth;
int boxheight = StatePtr->boxheight;
static int oldmousex, oldmousey, oldboxwidth, oldboxheight;
short junk;
if (StatePtr->zoommode) {
/* erase any old rectangle */
drawmode(OVERDRAW);
color(0);
recti(oldmousex, oldmousey,
oldmousex + oldboxwidth - 1, oldmousey + oldboxheight - 1 );
drawmode(NORMALDRAW);
readsource(SRC_ZBUFFER);
if (shademode == FLAT) {
rectzoom(StatePtr->xzoom, StatePtr->yzoom);
rectcopy(StatePtr->mousex, StatePtr->mousey,
StatePtr->mousex + boxwidth, StatePtr->mousey + boxheight,
0, 0 );
}
else
/* Gouraud Shading */
smoothcopy() ;
gRGBcolor(&junk, &junk, &junk); /* hack to flush pipe */
swapbuffers();
}
else {
/* draw zooming rectangle in overlays when it changes */
if ((StatePtr->mousex == oldmousex) &&
(StatePtr->mousey == oldmousey) &&
(boxwidth == oldboxwidth) &&
(boxheight == oldboxheight) ) {
;
}
else {
drawmode(OVERDRAW);
color(0);
recti(oldmousex, oldmousey,
oldmousex + oldboxwidth - 1, oldmousey + oldboxheight - 1 );
color(1);
recti(StatePtr->mousex, StatePtr->mousey,
StatePtr->mousex + boxwidth - 1,
StatePtr->mousey + boxheight - 1 );
oldmousex = StatePtr->mousex;
oldmousey = StatePtr->mousey;
oldboxwidth = boxwidth;
oldboxheight = boxheight;
drawmode(NORMALDRAW);
}
}
}
/* store pixels read for gouraud zoom */
unsigned long *cbuf;
makebuf() {
/* compute source rect size based on window size and zoom factor */
/* malloc a buffer based on the computed size */
static size = 0;
int msize;
long xsrc,ysrc;
int ixzoom = (int) (StatePtr->xzoom + .5);
int iyzoom = (int) (StatePtr->yzoom + .5);
/* Gouraud shading requires (n+1) points to gouraud shade (n) points */
StatePtr->width++; /* n+1 */
StatePtr->height++;
StatePtr->boxwidth = StatePtr->width / ixzoom;
StatePtr->boxheight =StatePtr->height / iyzoom;
xsrc = (long)(StatePtr->width) ;
ysrc = (long)(StatePtr->height) ;
msize = (xsrc) * (ysrc);
if (msize != size) {
stepunit((int)ixzoom,(int)iyzoom);
winconstraints();
if (size > 0)
free(cbuf);
if ((cbuf=(unsigned long*)malloc(msize*4)) == 0) {
fprintf(stderr," ERROR: can't malloc %d longs. abort.\n",msize);
gexit() ;
exit(1);
}
size = msize;
}
}
smoothcopy() {
/* read specified pixels, then draw gouraud shaded polygons */
/* assume that matrix and viewport are set up 1-to-1 object-to-pixel */
register x,y;
register unsigned long *cp0,*cp1;
register short *cp0s,*cp1s;
long width;
long height;
long xfinal,yfinal;
long vbuf[8];
float fzoomx;
float fzoomy;
float fzoomz;
makebuf() ;
width = StatePtr->boxwidth ;
height = StatePtr->boxheight ;
xfinal = width ;
yfinal = height ;
lrectread(StatePtr->mousex,StatePtr->mousey,
(StatePtr->mousex + width - 1),
(StatePtr->mousey + height - 1),cbuf);
pushmatrix();
fzoomx = StatePtr->xzoom ;
fzoomy = StatePtr->yzoom ;
fzoomz = 0.0 ;
scale((float)fzoomx,(float)fzoomy,(float)fzoomz);
for (y=0; y<yfinal; y++) {
vbuf[1] = vbuf[3] = y;
vbuf[5] = vbuf[7] = y+1;
cp0 = &cbuf[y * width];
cp1 = &cbuf[(y+1) * width + 1];
for (x=0; x<xfinal; x++) {
vbuf[0] = vbuf[6] = x;
vbuf[2] = vbuf[4] = x+1;
bgnpolygon();
cpack(*cp0++);
v2i(vbuf);
cpack(*cp0);
v2i(vbuf+2);
cpack(*cp1--);
v2i(vbuf+4);
cpack(*cp1++);
v2i(vbuf+6);
endpolygon();
cp1 += 1;
}
}
popmatrix();
/* Restore Correct Values */
--StatePtr->width ; /* n */
--StatePtr->height ;
}
void
ReadImage(name)
char *name;
{
IMAGE *image;
RGBvalue *r, *g, *b, *rp, *gp, *bp;
int i, j, y, dx, dy;
if ((image = iopen(name,"r")) == NULL) {
fprintf(stderr, "%s: can't open image file %s\n", CmdName, name);
exit(1);
}
if (image->zsize < 3) {
fprintf(stderr, "%s: image file is not an rgb image", CmdName);
exit(1);
}
dx = image->xsize;
dy = image->ysize;
r = (RGBvalue *) malloc(dx*dy*sizeof(RGBvalue));
g = (RGBvalue *) malloc(dx*dy*sizeof(RGBvalue));
b = (RGBvalue *) malloc(dx*dy*sizeof(RGBvalue));
for (y=0, rp=r, gp=g, bp=b; y < dy; y++, rp+=dx, gp+=dx, bp+=dx) {
getrow(image, ir, y, 0); ShrinkRow(dx, ir, rp);
getrow(image, ig, y, 1); ShrinkRow(dx, ig, gp);
getrow(image, ib, y, 2); ShrinkRow(dx, ib, bp);
}
/***
save image parameters in global state (for WriteImage()).
***/
StatePtr->r = r;
StatePtr->g = g;
StatePtr->b = b;
StatePtr->width = dx;
StatePtr->height = dy;
}
/***
Assumes double buffer mode.
***/
void
Drawit()
{
RGBvalue *r, *g, *b, *rp, *gp, *bp;
int y, dx, dy;
/***
get image parameters from global state.
***/
r = StatePtr->r;
g = StatePtr->g;
b = StatePtr->b;
dx = StatePtr->width;
dy = StatePtr->height;
/***
write out image to the all buffers (especially the zbuffer).
***/
#ifndef NOTDEF
for (y=0, rp=r, gp=g, bp=b; y < dy; y++, rp+=dx, gp+=dx, bp+=dx) {
cmov2i(0, y);
writeRGB((short) dx, rp, gp, bp);
}
#else
/***
Note: this block of code doesn't work yet...
***/
{
int x, y;
int *pixelp, pixelBuf[1280];
rp = r; gp = g; bp = b;
for (y = 0; y < dy; y++) {
pixelp = pixelBuf;
for (x = 0; x < dx; x++) {
PACK_RGB(*pixelp, *rp, *gp, *bp);
pixelp++, rp++, gp++, bp++;
}
(void) lrectwrite(0, y, dx - 1, y, pixelp);
}
}
#endif
}
static enum {
MACH_ECLIPSE,
MACH_CLOVER2, /* Doesn't work on CLOVER1 */
MACH_STAPUFT,
MACH_VENICE,
MACH_ELAN
} machine;
figure_machine()
{
char t[20];
char mystring[60];
static char ecl[] = "GL4DPI";
static char cl2[] = "GL4DGT";
static char stp[] = "GL4DVGX";
static char ven[] = "GL4DRE";
static char eln[] = "GL4DXG";
gversion(t);
if (strncmp(t, ecl, strlen(ecl)) == 0)
machine = MACH_ECLIPSE;
else if (strncmp(t, cl2, strlen(cl2)) == 0)
machine = MACH_CLOVER2;
else if (strncmp(t, stp, strlen(stp)) == 0)
machine = MACH_STAPUFT;
else if (strncmp(t, ven, strlen(ven)) == 0)
machine = MACH_VENICE;
else if (strncmp(t, eln, strlen(eln)) == 0)
machine = MACH_ELAN;
else {
sprintf(mystring, "inform 'Sorry, closeup does not work on %s machines'", t);
system(mystring);
gexit();
exit(1);
}
if ((getgdesc(GD_BITS_NORM_DBL_RED) + getgdesc(GD_BITS_NORM_DBL_GREEN) + getgdesc(GD_BITS_NORM_DBL_BLUE)) < 12) {
sprintf(mystring, "Sorry, closeup needs at least 12 bitplanes to run.");
system(mystring);
gexit();
exit(1);
}
}
void
WriteImage()
{
if (machine == MACH_ECLIPSE ||
machine == MACH_ELAN)
{
zdraw(TRUE);
Drawit();
zdraw(FALSE);
frontbuffer (TRUE);
Drawit();
}
else
{
zdraw(TRUE);
frontbuffer(TRUE);
Drawit();
zdraw(FALSE);
}
frontbuffer(FALSE);
}
/***
Copy an image from (to) the zbuffer to (from) the back buffer.
The image is the entire contents of the window.
Assumes doublebuffer mode.
***/
void
SwapImage(fromz)
Bool fromz; /* TRUE = copy from "z" to "back" buffer, FALSE = vice versa */
{
short junk;
if (fromz) {
readsource(SRC_ZBUFFER);
frontbuffer(FALSE);
backbuffer(TRUE);
zdraw(FALSE);
}
else {
fprintf(stderr, "SwapImage: doesn't work!\n");
}
rectzoom(1.0, 1.0);
rectcopy(0, 0, StatePtr->width - 1, StatePtr->height - 1, 0, 0);
gRGBcolor(&junk, &junk, &junk); /* hack to flush pipe */
}
/***
Shrink an array of shorts into an array of bytes.
***/
void
ShrinkRow(cols, sp, bp)
int cols;
u_short *sp;
RGBvalue *bp;
{
while (cols--) {
*bp++ = *sp++;
}
}